package com.codeman.bytebuddy.component;

import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelCollection;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.description.annotation.AnnotationDescription;
import net.bytebuddy.description.modifier.Visibility;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.FieldAccessor;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class ByteBuddyService {

    public final static Map<String, Class<?>> VIRTUAL_CLASS_MAP = new ConcurrentHashMap<>();

    public static void main(String[] args) throws IOException {
        new ByteBuddyService().makeProjectGroupExcelVOClass(null, null);
    }

    public void makeProjectGroupExcelVOClass(Class userClass, ClassLoader contextClassLoader) throws IOException {
        String name = "com.codeman.bytebuddy.virtual.ProjectGroupExcelVO";
        if (VIRTUAL_CLASS_MAP.get(name) == null) {
            DynamicType.Unloaded<Object> projectGroupExcelVODT = new ByteBuddy()
                    .subclass(Object.class)// 增强方式：目标类生成子类
                    .name(name) // 自定义生成的类名：包名+类名
                    .defineField("groupName", String.class, Modifier.PRIVATE)
                    .annotateField(AnnotationDescription.Builder.ofType(Excel.class)
                            .define("name", "小组名称")
                            .define("needMerge", true)
                            .define("width", 20.0d)
                            .define("height", 8.0d)
                            .build())
                    .defineMethod("getGroupName", String.class, Modifier.PUBLIC)
                    .intercept(FieldAccessor.ofBeanProperty())
                    .defineMethod("setGroupName", void.class, Visibility.PUBLIC)
                    .withParameters(String.class)
                    .intercept(FieldAccessor.ofBeanProperty())
                    .defineField("groupSlogan", String.class, Modifier.PRIVATE)
                    .annotateField(AnnotationDescription.Builder.ofType(Excel.class)
                            .define("name", "小组口号")
                            .define("needMerge", true)
                            .define("width", 20.0d)
                            .define("height", 8.0d)
                            .build())
                    .defineMethod("getGroupSlogan", String.class, Modifier.PUBLIC)
                    .intercept(FieldAccessor.ofBeanProperty())
                    .defineMethod("setGroupSlogan", void.class, Visibility.PUBLIC)
                    .withParameters(String.class)
                    .intercept(FieldAccessor.ofBeanProperty())
                    .defineField("groupType", String.class, Modifier.PRIVATE)
                    .annotateField(AnnotationDescription.Builder.ofType(Excel.class)
                            .define("name", "小组类型")
                            .define("needMerge", true)
                            .define("width", 20.0d)
                            .define("height", 8.0d)
                            .build())
                    .defineMethod("getGroupType", String.class, Modifier.PUBLIC)
                    .intercept(FieldAccessor.ofBeanProperty())
                    .defineMethod("setGroupType", void.class, Visibility.PUBLIC)
                    .withParameters(String.class)
                    .intercept(FieldAccessor.ofBeanProperty())
                    .defineField("groupUsers", TypeDescription.Generic.Builder.parameterizedType(List.class, userClass).build(), Modifier.PRIVATE)
                    .annotateField(AnnotationDescription.Builder.ofType(ExcelCollection.class)
                            .define("name", "组员信息")
                            .build())
                    .defineMethod("getGroupUsers", TypeDescription.Generic.Builder.parameterizedType(List.class, userClass).build(), Modifier.PUBLIC)
                    .intercept(FieldAccessor.ofBeanProperty())
                    .defineMethod("setGroupUsers", void.class, Visibility.PUBLIC)
                    .withParameters(TypeDescription.Generic.Builder.parameterizedType(List.class, userClass).build())
                    .intercept(FieldAccessor.ofBeanProperty())
                    .make();// 编译生成该类

//            projectGroupExcelVODT.saveIn(new File("D:\\zhj\\code\\byte-buddy\\target"));// 将类Class文件保存文件夹
            Class<?> projectGroupExcelVOClass = projectGroupExcelVODT.load(contextClassLoader).getLoaded();
            VIRTUAL_CLASS_MAP.put(name, projectGroupExcelVOClass);
        }
    }

    public void makeGroupUserExcelVOClass(ClassLoader contextClassLoader) throws IOException {
        String name = "com.codeman.bytebuddy.virtual.GroupUserExcelVO";
        if (VIRTUAL_CLASS_MAP.get(name) == null) {

            DynamicType.Unloaded<Object> groupUserExcelVODT = new ByteBuddy()
                    .subclass(Object.class)// 增强方式：目标类生成子类
                    .name(name) // 自定义生成的类名：包名+类名
                    .defineField("name", String.class, Modifier.PRIVATE)
                    .annotateField(AnnotationDescription.Builder.ofType(Excel.class)
                            .define("name", "组员名字")
                            .define("width", 20.0d)
                            .define("height", 8.0d)
                            .build())
                    .defineMethod("getName", String.class, Modifier.PUBLIC)
                    .intercept(FieldAccessor.ofBeanProperty())
                    .defineMethod("setName", void.class, Visibility.PUBLIC)
                    .withParameters(String.class)
                    .intercept(FieldAccessor.ofBeanProperty())
                    .defineField("phone", String.class, Modifier.PRIVATE)
                    .annotateField(AnnotationDescription.Builder.ofType(Excel.class)
                            .define("name", "组员电话")
                            .define("width", 20.0d)
                            .define("height", 8.0d)
                            .build())
                    .defineMethod("getPhone", String.class, Modifier.PUBLIC)
                    .intercept(FieldAccessor.ofBeanProperty())
                    .defineMethod("setPhone", void.class, Visibility.PUBLIC)
                    .withParameters(String.class)
                    .intercept(FieldAccessor.ofBeanProperty())
                    .defineField("age", Integer.class, Modifier.PRIVATE)
                    .annotateField(AnnotationDescription.Builder.ofType(Excel.class)
                            .define("name", "年龄")
                            .define("width", 20.0d)
                            .define("height", 8.0d)
                            .build())
                    .defineMethod("getAge", Integer.class, Modifier.PUBLIC)
                    .intercept(FieldAccessor.ofBeanProperty())
                    .defineMethod("setAge", void.class, Visibility.PUBLIC)
                    .withParameters(Integer.class)
                    .intercept(FieldAccessor.ofBeanProperty())
                    .make();// 编译生成该类

//        groupUserExcelVODT.saveIn(new File("D:\\zhj\\code\\byte-buddy\\target"));// 将类Class文件保存文件夹
            Class<?> projectGroupExcelVOClass = groupUserExcelVODT.load(contextClassLoader).getLoaded();
            VIRTUAL_CLASS_MAP.put(name, projectGroupExcelVOClass);
        }

    }


}
